package com.ebupt.migu.music.songlist.service.impl;

import com.ebupt.migu.music.common.entity.ResultObject;
import com.ebupt.migu.music.common.util.DateUtil;
import com.ebupt.migu.music.songlist.dto.QueryDto;
import com.ebupt.migu.music.songlist.mapper.EffectTrackMapper;
import com.ebupt.migu.music.songlist.service.EffectTrackService;
import com.ebupt.migu.music.songlist.vo.ActionVO;
import com.ebupt.migu.music.songlist.vo.BdListVo;
import com.ebupt.migu.music.songlist.vo.RankVO;
import com.ebupt.migu.music.songlist.vo.TrendVO;
import com.ebupt.migu.songlist.entity.BdFunnel;
import com.ebupt.migu.songlist.entity.BdPvUvInfo;
import com.ebupt.migu.songlist.entity.BdRetention;
import com.ebupt.migu.songlist.enums.ActionEnum;
import com.ebupt.migu.songlist.enums.TimeEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author tz
 */
@Slf4j
@Service
public class EffectTrackServiceImpl implements EffectTrackService {

    @Autowired
    private EffectTrackMapper effectTrackMapper;

    @Override
    public ResultObject bdList() {
        BdListVo vo = BdListVo.builder()
                .action(effectTrackMapper.action())
                .retention(effectTrackMapper.retention())
                .funnel(effectTrackMapper.funnel())
                .build();
        return new ResultObject().success("ok",vo);
    }

    @Override
    public ResultObject actionTrend(QueryDto queryDto) {
        queryDto.setFlag("bd");
        // 查询按小时的详细数据
        List<BdPvUvInfo> bdPvUvInfos = effectTrackMapper.listAll(dealParam(queryDto));
        // 处理结果数据
        List<TrendVO> vo = new ArrayList<>();
        queryDto.getContents().forEach(q -> {
            // 返回模板数组，有时间轴
            List<ActionVO> a1 = queryDto.getTimeList().stream().map(e -> new ActionVO(e, 0, 0)).collect(Collectors.toList());
            // 条件查询的数组，不一定所有时间点有数据
            List<ActionVO> a2 = bdPvUvInfos.stream().filter(bdPvUvInfo -> q.equals(bdPvUvInfo.getContentAddName())).map(c -> {
                ActionVO av = new ActionVO(c.getDtH() != null ? c.getDtH() : c.getDt().replaceAll("-",""), 0, 0);
                if (queryDto.getActionType().equals(ActionEnum.AUDITION.getCode())) {
                    av.setPv(c.getListenPv());
                    av.setUv(c.getListenUv());
                }
                if (queryDto.getActionType().equals(ActionEnum.COLLECT.getCode())) {
                    av.setPv(c.getCollectPv());
                    av.setUv(c.getCollectUv());
                }
                if (queryDto.getActionType().equals(ActionEnum.DOWNLOAD.getCode())) {
                    av.setPv(c.getDownloadPv());
                    av.setUv(c.getDownloadUv());
                }
                if (queryDto.getActionType().equals(ActionEnum.SHARE.getCode())) {
                    av.setPv(c.getSharePv());
                    av.setUv(c.getShareUv());
                }
                if (queryDto.getActionType().equals(ActionEnum.COMMENT.getCode())) {
                    av.setPv(c.getAddCommentPv());
                    av.setUv(c.getAddCommentUv());
                }
                return av;
            }).collect(Collectors.toList());
            // 不同时间截取长度对比
            int index = queryDto.getTimeType().equals(TimeEnum.DAY.getCode()) ? 11 : 8;
            a1.forEach(a -> {
                a2.forEach(b -> {
                    if (a.getTime().substring(0,index).equals(b.getTime().substring(0,index))){
                        a.setPv(b.getPv());
                        a.setUv(b.getUv());
                    }
                });
            });
            vo.add(new TrendVO(q,a1));
        });
        return new ResultObject().success("ok",vo);
    }

    private QueryDto dealParam(QueryDto queryDto) {
        // 通过时间类型确定查询范围
        Date now = new Date();
        Calendar c = Calendar.getInstance();
        c.setTime(now);
        String startTime;
        String endTime;
        List<String> timeList = new ArrayList<>();
        if (queryDto.getTimeType().equals(TimeEnum.DAY.getCode())) {
            c.add(Calendar.DAY_OF_MONTH,-1);
            startTime = DateUtil.parseDateToStr(c.getTime(),DateUtil.DATE_FORMAT_YYYYMMDD_HH).concat(":00");
            endTime = DateUtil.parseDateToStr(now,DateUtil.DATE_FORMAT_YYYYMMDD_HH).concat(":59");
            while (c.getTime().before(now)){
                c.add(Calendar.HOUR,1);
                timeList.add(DateUtil.parseDateToStr(c.getTime(),DateUtil.DATE_FORMAT_YYYYMMDD_HH).concat(":00"));
            }
        } else {
            if (queryDto.getTimeType().equals(TimeEnum.WEEK.getCode())) {
                c.add(Calendar.DAY_OF_MONTH,-7);
            }
            if (queryDto.getTimeType().equals(TimeEnum.MONTH.getCode())) {
                c.add(Calendar.DAY_OF_MONTH,-30);
            }
            // 开始日期
            startTime = DateUtil.parseDateToStr(c.getTime(),DateUtil.DATE_FORMAT_YYYYMMDD).concat(" 00:00");
            // 结束日期
            endTime = DateUtil.parseDateToStr(now,DateUtil.DATE_FORMAT_YYYYMMDD).concat(" 00:00");
            while (c.getTime().before(now)){
                timeList.add(DateUtil.parseDateToStr(c.getTime(),DateUtil.DATE_FORMAT_YYYYMMDD));
                c.add(Calendar.DAY_OF_MONTH,1);
            }
        }
        queryDto.setStartTime(startTime);
        queryDto.setEndTime(endTime);
        queryDto.setTimeList(timeList);
        return queryDto;
    }

    @Override
    public ResultObject retention(QueryDto queryDto) {
        List<BdRetention> bdRetentions = effectTrackMapper.retentionList(queryDto);
        return new ResultObject().success("ok",bdRetentions);
    }

    @Override
    public ResultObject actionFunnel(QueryDto queryDto) {
        List<BdFunnel> bdFunnels = effectTrackMapper.funnelList(queryDto);
        return new ResultObject().success("ok",bdFunnels);
    }

    @Override
    public ResultObject songRank(QueryDto queryDto) {
        queryDto.setFlag("song");
        List<BdPvUvInfo> bdPvUvInfos = effectTrackMapper.countAll(dealParam(queryDto));
        List<BdPvUvInfo> collect = bdPvUvInfos.stream().sorted(
                Comparator.comparingInt(BdPvUvInfo::getListenUv).reversed()).limit(10).collect(Collectors.toList());
        List<RankVO> vo = collect.stream().map(e -> {
            RankVO rankVO = new RankVO();
            BeanUtils.copyProperties(e, rankVO);
            return rankVO;
        }).collect(Collectors.toList());
        return new ResultObject().success("ok",vo);
    }
}